using net_work.Common.Request;
using net_work.Common.Result;
using net_work.Data.DTO.Sys;
using net_work.Data.Entity.Sys;
using net_work.Data.VO.Sys;
using net_work.IRepository.Sys;
using net_work.IRepository.System;
using net_work.IService.Sys;

namespace net_work.Service.Sys;

public class StudentService(
    ITransactionManager transactionManager,
    IStudentRepository studentRepository,
    IPersonRepository personRepository,
    IAdministrativeClassRepository administrativeClassRepository)
    : IStudentService
{
    public Task<PagedResult<StudentResult>> GetStudentsPagedAsync(PagedRequest request)
    {
        return studentRepository.GetStudentPagedAsync(request);
    }

    public Task<Student?> SelectByIdAsync(long studentId)
    {
        return studentRepository.GetByIdAsync(studentId);
    }

    public async Task<long> InsertStudent(StudentAddRequest studentAddRequest)
    {
        var person = await personRepository.GetByIdAsync(studentAddRequest.PersonId);
        if (person == null)
        {
            return -1;
        }

        var administrativeClass = await administrativeClassRepository.GetByIdAsync(studentAddRequest.ClassId);
        if (administrativeClass == null)
        {
            return -1;
        }

        try
        {
            await transactionManager.BeginTransactionAsync();
            var studentId = await studentRepository.InsertAsync(studentAddRequest);
            if (studentId <= 0)
            {
                throw new Exception("插入学生失败");
            }

            var updateClassNumAsync =
                await administrativeClassRepository.UpdateClassNumAsync(administrativeClass.Id,
                    administrativeClass.ClassNum + 1);
            if (!updateClassNumAsync)
            {
                throw new Exception("更新班级人数失败");
            }

            await transactionManager.CommitTransactionAsync();
            return studentId;
        }
        catch (Exception e)
        {
            await transactionManager.RollbackTransactionAsync();
            return -1;
        }
    }

    public async Task<int> UpdateStudent(StudentUpdateRequest studentUpdateRequest)
    {
        if (studentUpdateRequest.Id <= 0)
        {
            return -1;
        }

        var person = await personRepository.GetByIdAsync(studentUpdateRequest.PersonId);
        if (person == null)
        {
            return -1;
        }

        var administrativeClass = await administrativeClassRepository.GetByIdAsync(studentUpdateRequest.ClassId);
        if (administrativeClass == null)
        {
            return -1;
        }

        try
        {
            await transactionManager.BeginTransactionAsync();

            if (studentUpdateRequest.ClassId == administrativeClass.Id)
            {
                var updateAsync = await studentRepository.UpdateAsync(studentUpdateRequest);
                if (!updateAsync)
                {
                    throw new Exception("更新学生失败");
                }

                await transactionManager.CommitTransactionAsync();
                return 1;
            }

            var updateStudentAsync = await studentRepository.UpdateAsync(studentUpdateRequest);
            if (!updateStudentAsync)
            {
                throw new Exception("更新学生失败");
            }

            var updateClassNumAsync1 =
                await administrativeClassRepository.UpdateClassNumAsync(administrativeClass.Id,
                    administrativeClass.ClassNum - 1);

            var updateClassNumAsync2 =
                await administrativeClassRepository.UpdateClassNumAsync(studentUpdateRequest.ClassId,
                    administrativeClass.ClassNum + 1);

            if (!updateClassNumAsync1 || !updateClassNumAsync2)
            {
                throw new Exception("更新班级人数失败");
            }

            await transactionManager.CommitTransactionAsync();
            return 1;
        }
        catch (Exception e)
        {
            await transactionManager.RollbackTransactionAsync();
            return -1;
        }
    }

    public async Task<int> DeleteStudentByIds(List<long> ids)
    {
        var pagedResult1 = await studentRepository.GetPagedAsync(new PagedRequest(1, PageSizeEnum.Unlimited,
            [new FilterCondition("Id", FilterOperator.In, ids)]));
        var classIdCounts = pagedResult1.Data.GroupBy(s => s.ClassId).ToDictionary(g => g.Key, g => g.Count());

        var pagedResult2 = await administrativeClassRepository.GetPagedAsync(new PagedRequest(1, PageSizeEnum.Unlimited,
            [new FilterCondition("Id", FilterOperator.In, classIdCounts.Keys)]));
        if (pagedResult2.TotalRecords != classIdCounts.Count)
        {
            return -1;
        }

        var oldClassNumDict = pagedResult2.Data.ToDictionary(c => c.Id, c => c.ClassNum);

        try
        {
            await transactionManager.BeginTransactionAsync();

            var deleteSuccess = await studentRepository.DeleteByIdsAsync(ids);
            if (!deleteSuccess)
            {
                throw new InvalidOperationException("删除学生失败");
            }

            foreach (var (classId, decrement) in classIdCounts)
            {
                var newClassNum = oldClassNumDict[classId] - decrement;
                if (newClassNum < 0)
                {
                    throw new InvalidOperationException($"班级 {classId} 的人数更新为负数");
                }

                var updateSuccess = await administrativeClassRepository.UpdateClassNumAsync(classId, newClassNum);
                if (!updateSuccess)
                {
                    throw new InvalidOperationException($"更新班级 {classId} 人数失败");
                }
            }

            await transactionManager.CommitTransactionAsync();
            return 1;
        }
        catch (Exception e)
        {
            await transactionManager.RollbackTransactionAsync();
            return -1;
        }
    }
}